# -*- coding : utf-8-*-
import base64
import os
import sys

from PyQt5 import QtCore, QtGui, uic, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QMainWindow, QDesktopWidget, QInputDialog, QMessageBox
import qrcode
# from PIL import ImageGrab, Image, ImageQt
# import PySide6  
# from PySide6 import QtCore, QtGui  
# import PIL  
# from PIL import Image, ImageQt ,ImageGrab
# from PIL.ImageQt import ImageQt
# from PyQt5.QtGui import QImage

from PIL import Image,ImageGrab
# from PIL.ImageQt import ImageQt

import cv2
import numpy as np
from pyzbar import pyzbar
import datetime
import gzip
from io import BytesIO
import wmi
import base64
from pyDes import *
from cacheout import LFUCache

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(920, 665)

        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(0, 0, 921, 661))
        self.tabWidget.setObjectName("tabWidget")
        self.Gen = QtWidgets.QWidget()
        self.Gen.setObjectName("Gen")
        self.groupBox1 = QtWidgets.QGroupBox(self.Gen)
        self.groupBox1.setGeometry(QtCore.QRect(0, 0, 471, 511))
        self.groupBox1.setObjectName("groupBox1")
        self.lb_qrcode = QtWidgets.QLabel(self.groupBox1)
        self.lb_qrcode.setGeometry(QtCore.QRect(10, 30, 451, 471))
        self.lb_qrcode.setObjectName("lb_qrcode")
        self.groupBox = QtWidgets.QGroupBox(self.Gen)
        self.groupBox.setGeometry(QtCore.QRect(0, 510, 401, 81))
        self.groupBox.setObjectName("groupBox")
        self.label_2 = QtWidgets.QLabel(self.groupBox)
        self.label_2.setGeometry(QtCore.QRect(10, 20, 61, 21))
        self.label_2.setObjectName("label_2")
        self.txt_img_size = QtWidgets.QLineEdit(self.groupBox)
        self.txt_img_size.setGeometry(QtCore.QRect(70, 20, 61, 20))
        self.txt_img_size.setObjectName("txt_img_size")
        self.label_3 = QtWidgets.QLabel(self.groupBox)
        self.label_3.setGeometry(QtCore.QRect(140, 20, 31, 21))
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.groupBox)
        self.label_4.setGeometry(QtCore.QRect(180, 20, 61, 21))
        self.label_4.setObjectName("label_4")
        self.cb_level = QtWidgets.QComboBox(self.groupBox)
        self.cb_level.setGeometry(QtCore.QRect(240, 20, 51, 22))
        self.cb_level.setObjectName("cb_level")
        self.cb_level.addItem("")
        self.cb_level.addItem("")
        self.cb_level.addItem("")
        self.cb_level.addItem("")
        self.label_5 = QtWidgets.QLabel(self.groupBox)
        self.label_5.setGeometry(QtCore.QRect(180, 50, 51, 21))
        self.label_5.setObjectName("label_5")
        self.txt_split_size = QtWidgets.QLineEdit(self.groupBox)
        self.txt_split_size.setGeometry(QtCore.QRect(240, 50, 61, 20))
        self.txt_split_size.setObjectName("txt_split_size")
        self.label_6 = QtWidgets.QLabel(self.groupBox)
        self.label_6.setGeometry(QtCore.QRect(310, 50, 31, 21))
        self.label_6.setObjectName("label_6")
        self.label_7 = QtWidgets.QLabel(self.groupBox)
        self.label_7.setGeometry(QtCore.QRect(10, 50, 61, 21))
        self.label_7.setObjectName("label_7")
        self.txt_sleep_gen = QtWidgets.QLineEdit(self.groupBox)
        self.txt_sleep_gen.setGeometry(QtCore.QRect(70, 50, 61, 20))
        self.txt_sleep_gen.setObjectName("txt_sleep_gen")
        self.label_8 = QtWidgets.QLabel(self.groupBox)
        self.label_8.setGeometry(QtCore.QRect(140, 50, 31, 21))
        self.label_8.setObjectName("label_8")
        self.groupBox_2 = QtWidgets.QGroupBox(self.Gen)
        self.groupBox_2.setGeometry(QtCore.QRect(420, 530, 511, 61))
        self.groupBox_2.setObjectName("groupBox_2")
        self.btnGen = QtWidgets.QPushButton(self.groupBox_2)
        self.btnGen.setGeometry(QtCore.QRect(50, 20, 61, 23))
        self.btnGen.setObjectName("btnGen")
        self.label_9 = QtWidgets.QLabel(self.groupBox_2)
        self.label_9.setGeometry(QtCore.QRect(200, 20, 121, 21))
        self.label_9.setObjectName("label_9")
        self.lb_qrnum = QtWidgets.QLabel(self.groupBox_2)
        self.lb_qrnum.setGeometry(QtCore.QRect(330, 20, 71, 21))
        self.lb_qrnum.setObjectName("lb_qrnum")
        self.lb_qrindex = QtWidgets.QLabel(self.groupBox_2)
        self.lb_qrindex.setGeometry(QtCore.QRect(400, 20, 61, 21))
        self.lb_qrindex.setObjectName("lb_qrindex")
        self.lb_filepath = QtWidgets.QLabel(self.Gen)
        self.lb_filepath.setGeometry(QtCore.QRect(130, 590, 781, 31))
        self.lb_filepath.setObjectName("lb_filepath")
        self.cb_file = QtWidgets.QCheckBox(self.Gen)
        self.cb_file.setGeometry(QtCore.QRect(10, 590, 111, 21))
        self.cb_file.setObjectName("cb_file")
        self.label_12 = QtWidgets.QLabel(self.Gen)
        self.label_12.setGeometry(QtCore.QRect(470, 410, 441, 21))
        self.label_12.setObjectName("label_12")
        self.txt_input_miss = QtWidgets.QPlainTextEdit(self.Gen)
        self.txt_input_miss.setGeometry(QtCore.QRect(500, 440, 421, 101))
        self.txt_input_miss.setStatusTip("")
        self.txt_input_miss.setDocumentTitle("")
        self.txt_input_miss.setPlainText("")
        self.txt_input_miss.setObjectName("txt_input_miss")
        self.txt_input = QtWidgets.QPlainTextEdit(self.Gen)
        self.txt_input.setGeometry(QtCore.QRect(470, 20, 451, 391))
        self.txt_input.setStatusTip("")
        self.txt_input.setDocumentTitle("")
        self.txt_input.setPlainText("")
        self.txt_input.setObjectName("txt_input")
        self.label_17 = QtWidgets.QLabel(self.Gen)
        self.label_17.setGeometry(QtCore.QRect(470, 0, 441, 16))
        self.label_17.setObjectName("label_17")
        self.cb_miss = QtWidgets.QCheckBox(self.Gen)
        self.cb_miss.setGeometry(QtCore.QRect(480, 460, 21, 21))
        self.cb_miss.setText("")
        self.cb_miss.setObjectName("cb_miss")
        self.tabWidget.addTab(self.Gen, "")
        self.Rec = QtWidgets.QWidget()
        self.Rec.setObjectName("Rec")
        self.label_qrcode = QtWidgets.QLabel(self.Rec)
        self.label_qrcode.setGeometry(QtCore.QRect(0, 0, 701, 501))
        self.label_qrcode.setObjectName("label_qrcode")
        self.txt_rec = QtWidgets.QPlainTextEdit(self.Rec)
        self.txt_rec.setGeometry(QtCore.QRect(0, 520, 911, 121))
        self.txt_rec.setObjectName("txt_rec")
        self.groupBox_3 = QtWidgets.QGroupBox(self.Rec)
        self.groupBox_3.setGeometry(QtCore.QRect(740, 0, 191, 521))
        self.groupBox_3.setObjectName("groupBox_3")
        self.rb_screen = QtWidgets.QRadioButton(self.groupBox_3)
        self.rb_screen.setGeometry(QtCore.QRect(20, 30, 111, 16))
        self.rb_screen.setObjectName("rb_screen")
        self.rb_camera = QtWidgets.QRadioButton(self.groupBox_3)
        self.rb_camera.setGeometry(QtCore.QRect(20, 70, 111, 16))
        self.rb_camera.setObjectName("rb_camera")
        self.btn_recg = QtWidgets.QPushButton(self.groupBox_3)
        self.btn_recg.setGeometry(QtCore.QRect(20, 160, 75, 23))
        self.btn_recg.setObjectName("btn_recg")
        self.btn_lost = QtWidgets.QPushButton(self.groupBox_3)
        self.btn_lost.setGeometry(QtCore.QRect(0, 450, 151, 23))
        self.btn_lost.setObjectName("btn_lost")
        self.label = QtWidgets.QLabel(self.groupBox_3)
        self.label.setGeometry(QtCore.QRect(10, 210, 131, 16))
        self.label.setObjectName("label")
        self.txt_rect = QtWidgets.QLineEdit(self.groupBox_3)
        self.txt_rect.setGeometry(QtCore.QRect(10, 230, 141, 20))
        self.txt_rect.setObjectName("txt_rect")
        self.label_10 = QtWidgets.QLabel(self.groupBox_3)
        self.label_10.setGeometry(QtCore.QRect(10, 260, 121, 16))
        self.label_10.setObjectName("label_10")
        self.txt_sleep_rec = QtWidgets.QLineEdit(self.groupBox_3)
        self.txt_sleep_rec.setGeometry(QtCore.QRect(10, 280, 71, 20))
        self.txt_sleep_rec.setObjectName("txt_sleep_rec")
        self.label_11 = QtWidgets.QLabel(self.groupBox_3)
        self.label_11.setGeometry(QtCore.QRect(90, 280, 31, 21))
        self.label_11.setObjectName("label_11")
        self.label_15 = QtWidgets.QLabel(self.groupBox_3)
        self.label_15.setGeometry(QtCore.QRect(10, 320, 61, 20))
        self.label_15.setObjectName("label_15")
        self.label_tip = QtWidgets.QLabel(self.groupBox_3)
        self.label_tip.setGeometry(QtCore.QRect(10, 360, 161, 20))
        self.label_tip.setText("")
        self.label_tip.setObjectName("label_tip")
        self.label_16 = QtWidgets.QLabel(self.groupBox_3)
        self.label_16.setGeometry(QtCore.QRect(10, 500, 141, 16))
        self.label_16.setObjectName("label_16")
        self.txt_camera_index = QtWidgets.QLineEdit(self.groupBox_3)
        self.txt_camera_index.setGeometry(QtCore.QRect(40, 110, 21, 21))
        self.txt_camera_index.setObjectName("txt_camera_index")
        self.label_18 = QtWidgets.QLabel(self.groupBox_3)
        self.label_18.setGeometry(QtCore.QRect(20, 110, 21, 16))
        self.label_18.setObjectName("label_18")
        self.label_19 = QtWidgets.QLabel(self.groupBox_3)
        self.label_19.setGeometry(QtCore.QRect(70, 110, 81, 16))
        self.label_19.setObjectName("label_19")
        self.tabWidget.addTab(self.Rec, "")
        self.Reg = QtWidgets.QWidget()
        self.Reg.setObjectName("Reg")
        self.label_13 = QtWidgets.QLabel(self.Reg)
        self.label_13.setGeometry(QtCore.QRect(20, 20, 91, 16))
        self.label_13.setObjectName("label_13")
        self.label_macode = QtWidgets.QLabel(self.Reg)
        self.label_macode.setGeometry(QtCore.QRect(120, 20, 91, 16))
        self.label_macode.setText("")
        self.label_macode.setObjectName("label_macode")
        self.label_regtip = QtWidgets.QLabel(self.Reg)
        self.label_regtip.setGeometry(QtCore.QRect(20, 70, 54, 12))
        self.label_regtip.setObjectName("label_regtip")
        self.btn_money = QtWidgets.QPushButton(self.Reg)
        self.btn_money.setGeometry(QtCore.QRect(190, 60, 75, 23))
        self.btn_money.setObjectName("btn_money")
        self.groupBox_5 = QtWidgets.QGroupBox(self.Reg)
        self.groupBox_5.setGeometry(QtCore.QRect(360, 0, 551, 131))
        self.groupBox_5.setObjectName("groupBox_5")
        self.textBrowser = QtWidgets.QTextBrowser(self.groupBox_5)
        self.textBrowser.setGeometry(QtCore.QRect(0, 20, 551, 91))
        self.textBrowser.setObjectName("textBrowser")
        self.label_14 = QtWidgets.QLabel(self.Reg)
        self.label_14.setGeometry(QtCore.QRect(10, 130, 871, 21))
        self.label_14.setObjectName("label_14")
        self.groupBox_4 = QtWidgets.QGroupBox(self.Reg)
        self.groupBox_4.setGeometry(QtCore.QRect(10, 160, 891, 171))
        self.groupBox_4.setObjectName("groupBox_4")
        self.textBrowser_2 = QtWidgets.QTextBrowser(self.groupBox_4)
        self.textBrowser_2.setGeometry(QtCore.QRect(0, 20, 891, 141))
        self.textBrowser_2.setObjectName("textBrowser_2")
        self.tabWidget.addTab(self.Reg, "")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "文件二维码"))
        self.groupBox1.setTitle(_translate("MainWindow", "二维码图像"))
        self.lb_qrcode.setText(_translate("MainWindow", "二维码图像"))
        self.groupBox.setTitle(_translate("MainWindow", "二维码生成参数"))
        self.label_2.setText(_translate("MainWindow", "图像大小"))
        self.txt_img_size.setText(_translate("MainWindow", "300"))
        self.label_3.setText(_translate("MainWindow", "像素"))
        self.label_4.setText(_translate("MainWindow", "容错级别"))
        self.cb_level.setItemText(0, _translate("MainWindow", "7%"))
        self.cb_level.setItemText(1, _translate("MainWindow", "15%"))
        self.cb_level.setItemText(2, _translate("MainWindow", "25%"))
        self.cb_level.setItemText(3, _translate("MainWindow", "35%"))
        self.label_5.setText(_translate("MainWindow", "分割大小"))
        self.txt_split_size.setText(_translate("MainWindow", "132"))
        self.label_6.setText(_translate("MainWindow", "字节"))
        self.label_7.setText(_translate("MainWindow", "间隔时间"))
        self.txt_sleep_gen.setText(_translate("MainWindow", "40"))
        self.label_8.setText(_translate("MainWindow", "毫秒"))
        self.groupBox_2.setTitle(_translate("MainWindow", "控制区域"))
        self.btnGen.setText(_translate("MainWindow", "生成"))
        self.label_9.setText(_translate("MainWindow", "二维码数量及当前编号:"))
        self.lb_qrnum.setText(_translate("MainWindow", "1"))
        self.lb_qrindex.setText(_translate("MainWindow", "0"))
        self.lb_filepath.setText(_translate("MainWindow", "选择的文件路径"))
        self.cb_file.setText(_translate("MainWindow", "输入文件(选择)"))
        self.label_12.setText(_translate("MainWindow", "高级模式:输入未识别的文件块ID:指定起始块ID或列举所有的ID,然后点击\"生成\""))
        self.txt_input_miss.setPlaceholderText(_translate("MainWindow", "输入要生成二维码的文本"))
        self.txt_input.setPlaceholderText(_translate("MainWindow", "输入要生成二维码的文本"))
        self.label_17.setText(_translate("MainWindow", "输入文本用于生成二维码(也可选择文件见左下方)"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.Gen), _translate("MainWindow", "生成"))
        self.label_qrcode.setText(_translate("MainWindow", "待识别的图像,来源(屏幕(文件,看图软件打开即可)或摄像头)"))
        self.groupBox_3.setTitle(_translate("MainWindow", "控制区域"))
        self.rb_screen.setText(_translate("MainWindow", "从屏幕截图识别"))
        self.rb_camera.setText(_translate("MainWindow", "从摄像头识别"))
        self.btn_recg.setText(_translate("MainWindow", "识别"))
        self.btn_lost.setText(_translate("MainWindow", "找到未识别的文件块ID"))
        self.label.setText(_translate("MainWindow", "截图区域:默认左半屏"))
        self.txt_rect.setText(_translate("MainWindow", "0,0,0,0"))
        self.label_10.setText(_translate("MainWindow", "截图间隔时间"))
        self.txt_sleep_rec.setText(_translate("MainWindow", "100"))
        self.label_11.setText(_translate("MainWindow", "毫秒"))
        self.label_15.setText(_translate("MainWindow", "识别状态"))
        self.label_16.setText(_translate("MainWindow", "日志及识别结果"))
        self.txt_camera_index.setText(_translate("MainWindow", "0"))
        self.label_18.setText(_translate("MainWindow", "第"))
        self.label_19.setText(_translate("MainWindow", "个摄像头"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.Rec), _translate("MainWindow", "识别"))
        self.label_13.setText(_translate("MainWindow", "注册信息机器码:"))
        self.label_regtip.setText(_translate("MainWindow", "未注册"))
        self.btn_money.setText(_translate("MainWindow", "注册"))
        self.groupBox_5.setTitle(_translate("MainWindow", "注册码获取过程说明"))
        self.textBrowser.setHtml(_translate("MainWindow",
                                            "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
                                            "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
                                            "p, li { white-space: pre-wrap; }\n"
                                            "</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
                                            "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">1.发送邮件给<span style=\" font-weight:600;\">knightyi@qq.com</span>   主题:你的机器码(左侧第一行内容)<br />2.<span style=\" font-weight:600;\">knightyi@qq.com 回复你:付款方式（一般就是支付宝，微信啥的），金额(20元) </span></p>\n"
                                            "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600;\">3.发送支付凭证截图及</span>机器码<span style=\" font-weight:600;\">到邮箱knightyi@qq.com,支付时最好备注机器码<br />4.knightyi@qq.com 收到上一步内容后，发送注册码到你的邮箱 <br />5 点击 左侧的&quot;注册&quot;按钮 完成注册，会在本软件运行目录生成</span><span style=\" font-style:italic;\"> 注册文件</span><span style=\" font-family:\'JetBrains Mono\',\'monospace\'; font-size:9.8pt; font-style:italic; color:#6a8759;\">register.txt ，不要删除</span></p></body></html>"))
        self.label_14.setText(
            _translate("MainWindow", "注册权益说明:未注册不能接受超过10个文件块的内容,其大小为10*132（分割大小:可调,有上限），但软件理论上传输大小不限，越大越慢"))
        self.groupBox_4.setTitle(_translate("MainWindow", "功能用途说明"))
        self.textBrowser_2.setHtml(_translate("MainWindow",
                                              "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
                                              "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
                                              "p, li { white-space: pre-wrap; }\n"
                                              "</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
                                              "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">1.普通的二维码生成与识别<br />2.文件二维码的生成发送，接受与识别 (远程桌面与当前主机)<br />3.手机到电脑，电脑到手机间的信息传递(通过摄像头) 安卓有同名软件:文件二维码APP(手机间传输大小不限)</p>\n"
                                              "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p>\n"
                                              "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">4.技巧说明:</p>\n"
                                              "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">间隔时间值设小会加快生成或识别过程，可能会出现识别率降低</p>\n"
                                              "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">分割大小：太大会可能会出现识别率降低或报错</p>\n"
                                              "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">高级模式：用于只显示指定文件块ID或范围的二维码，要和识别模块的“找到未识别的文件块ID”按钮配合使用</p></body></html>"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.Reg), _translate("MainWindow", "注册与帮助"))





def capture_screen2(bbox):
    capScr = None
    try:
        capScr = np.array(ImageGrab.grab(bbox))
        capScr = cv2.cvtColor(capScr, cv2.COLOR_RGB2BGR)
    except:
        print("ecaptureScreen error");
    return capScr


def read_into_bytes(filename):
    data = None
    with open(filename, 'rb') as f:
        data = f.read(os.path.getsize(filename))  # f.readinto(buf)
    f.close()
    return data


def gzip_compress(buf):
    out = BytesIO()
    with gzip.GzipFile(fileobj=out, mode="wb") as f:
        f.write(buf)
    return out.getvalue()


def gzip_decompress(buf):
    input = BytesIO(buf)
    with gzip.GzipFile(fileobj=input) as f:
        result = f.read()
    return result


class Decoder(object):
    def __init__(self):
        self.dataArray = None
        self.receiveAll = False
        self.total = 2;
        self.index = 0;
        self.size = 0;
        self.ids = set()
        self.file_name = "NO_NAME"

    def decode(self, str_bytes):
        try:

            part = base64.b64decode(str_bytes)
            part_total = part[0:4]
            total = int.from_bytes(part_total, byteorder='big')
            part_index = part[4:8]
            index = int.from_bytes(part_index, byteorder='big')

            if total < 1 or total <= index:
                self.receiveAll = True
                return

            if self.dataArray is None:  # empty init
                self.dataArray = [None for _ in range(total)]

            if self.dataArray[index] is None:
                self.dataArray[index] = part[8:]
                self.ids.add(index)

            self.total = total
            self.index = index

            size = len(self.ids)
            self.size = size
            if total == size:
                self.receiveAll = True
                self.file_name = bytes.decode(self.dataArray[0])

        except Exception as e:
            self.receiveAll = True
            print("except occur! barcode.data" + str(str_bytes) + " e:\n", e)

    def receive(self, str_bytes):
        if self.receiveAll or str_bytes is None:
            return
        else:
            self.decode(str_bytes)


ext_list = ['.gz', '.7z', '.zip', '.rar', '.exe', '.tar']


class Encoder(object):
    def __init__(self):
        pass

    @staticmethod
    def encode(data_bytes, split_size, file_name):
        ext = os.path.splitext(file_name)[-1]
        need_press = True
        if ext:
            need_press = ext.lower() not in ext_list
        if need_press:
            data_bytes = gzip_compress(data_bytes)
            file_name = "gz1" + file_name
        else:
            file_name = "gz0" + file_name

        total_bytes = len(data_bytes)
        numChunks = int(total_bytes / split_size)
        n = numChunks
        if total_bytes % split_size > 0:
            n = n + 1
        print("encode", total_bytes, n, split_size)

        data_list = []
        total_part = int(n + 1).to_bytes(length=4, byteorder='big', signed=False)
        filename_part = bytes(file_name, encoding="utf8")
        zero_part = int(0).to_bytes(length=4, byteorder='big', signed=False)

        data_list.append(total_part + zero_part + filename_part)  # first index

        for i in range(0, numChunks):
            s_start = i * split_size
            s_end = s_start + split_size
            part = data_bytes[s_start:s_end]
            i_part = int(i + 1).to_bytes(length=4, byteorder='big', signed=False)
            data_list.append(total_part + i_part + part)

        if n > numChunks:
            rest_part = data_bytes[numChunks * split_size:total_bytes]
            rest_i_part = (numChunks + 1).to_bytes(length=4, byteorder='big', signed=False)
            data_list.append(total_part + rest_i_part + rest_part)

        return data_list



class MyDesigner(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MyDesigner, self).__init__(parent)
        self.ids = None
        self.qr_decoder = None
        self.setupUi(self)
        self.btnGen.clicked.connect(self.btn_gen_click)
        self.cb_file.clicked.connect(self.open_file)

        self.btn_recg.clicked.connect(self.rec_click)
        self.btn_lost.clicked.connect(self.find_lost)

        self.btn_money.clicked.connect(self.register)

        self.data_list = None
        self.thread = None
        self.cap = None

        self.cache = LFUCache()

    def create_qrcode(self, txt):
        # 设置二维码

        qr = qrcode.QRCode(
            version=1,
            error_correction=qrcode.constants.ERROR_CORRECT_L,
            box_size=6,
            border=2,
        )
        level = self.cb_level.currentText()
        levels = ['7%', '15%', '25%', '35%']
        levels_int = [1, 0, 3, 2]
        for i in range(0, 4):
            if level == levels[i]:
                qr.error_correction = levels_int[i]
                break
        # print('level', level, qr.error_correction)
        # 添加二维码跳转路径
        qr.add_data(txt)
        # 开启设置二维码颜色
        qr.make(fit=True)
        # 设置二维码颜色
        # img = qr.make_image(fill_color="black", back_color="white")
        # qimg = ImageQt(img)
        # qimg = QImage(imgqt)
        
        # 生成二维码图片
        img = qr.make_image(fill_color="black", back_color="white").convert("RGB")

        # 将PIL.Image对象转换为QImage对象
        # img_bytes = img.tobytes()
        # img_width = img.width
        # img_height = img.height
        qimg = QImage(img.tobytes(), img.width, img.height, 3 * img.width, QImage.Format_RGB888)

        # 将QImage对象转换为QPixmap对象
        return QPixmap.fromImage(qimg)
        

    def rec_click(self):
        if self.rb_camera.isChecked():
            self.cap = cv2.VideoCapture(int(self.txt_camera_index.text()))
        zt = self.btn_recg.text()
        if zt == '识别':
            if self.thread is not None and self.thread.isPause:
                self.thread.resume()
            else:
                # 创建线程
                self.qr_decoder = Decoder()
                self.thread = Runthread(-1, -1, int(self.txt_sleep_rec.text().strip()))
                # 连接信号
                self.thread.signal.connect(self.rec_image)  # 进程连接回传到GUI的事件
                # 开始线程
                self.thread.start()

            self.btn_recg.setText('暂停')
        else:
            self.thread.pause()  # 暂停停线程
            self.btn_recg.setText('识别')


    def camera_close(self):
        if self.cap:
            self.cap.release()

    def rec_qrcode(self, img):
        for barcode in pyzbar.decode(img):
            data = barcode.data  # print(myData)
            self.qr_decoder.receive(data)
            # draw qrcode box
            pts = np.array([barcode.polygon], np.int32)
            pts = pts.reshape((-1, 1, 2))
            cv2.polylines(img, [pts], True, (255, 0, 255), 5)
            pts2 = barcode.rect
            tips = str(self.qr_decoder.total) + "/" + str(self.qr_decoder.size) + "/" + str(
                self.qr_decoder.size / self.qr_decoder.total)
            cv2.putText(img, tips, (pts2[0], pts2[1]), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)

            self.label_tip.setText(
                str(self.qr_decoder.total) + "/" + str(self.qr_decoder.size) + "/" + str(self.qr_decoder.index))
            if self.qr_decoder.receiveAll:
                self.thread.cancel()
                self.camera_close()
                print("All data received! save to " + self.qr_decoder.file_name)
                if self.qr_decoder.size == 0:
                    self.txt_rec.setPlainText(data.decode())
                else:
                    out = BytesIO()
                    for i in range(1, len(self.qr_decoder.dataArray)):
                        out.write(self.qr_decoder.dataArray[i])
                    f_bytes = out.getvalue()
                    if self.qr_decoder.file_name.find('gz1') == 0:  # 处理压缩的
                        f_bytes = gzip_decompress(f_bytes)
                    if self.qr_decoder.file_name.find('NO_NAME') > -1:
                        self.txt_rec.setPlainText(bytes.decode(f_bytes))
                    else:
                        file_save_path = os.getcwd() + os.sep + self.qr_decoder.file_name[3:]
                        if os.path.isfile(file_save_path):
                            ext = os.path.splitext(file_save_path)[-1]
                            t = datetime.datetime.now()
                            s = "%s%s%s" % (t.hour, t.minute, t.second)
                            file_save_path = file_save_path + s + ext

                        self.txt_rec.setPlainText("文件保存在:" + file_save_path)
                        with open(file_save_path, 'bw') as f:
                            f.write(f_bytes)

    def find_lost(self):
        self.thread.pause()
        lost_data = []
        for i in range(0, self.qr_decoder.total):
            if i not in self.qr_decoder.ids:
                lost_data.append(i)
        self.txt_rec.setPlainText(str(lost_data).replace("[", "").replace("]", ""))
        self.thread.resume()

    def rec_image(self, msg):
        if msg == -1:
            self.btn_recg.setText("识别")
            return
        image = None
        if self.rb_screen.isChecked():
            rect = self.txt_rect.text().strip()  # .split(",")[:4]
            desktop = QApplication.desktop()
            if rect == '0,0,0,0':
                rect = 0, 0, int(desktop.width() * 0.5), desktop.height()
            else:
                rect = rect.split(",")[:4]
                rect = [int(i) for i in rect]

            image = capture_screen2(rect)
        else:
            success, img = self.cap.read()
            if success:
                img = cv2.resize(img, (480, 320))
                img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
                image = img

        self.rec_qrcode(image)
        showImage = QImage(image.data, image.shape[1], image.shape[0], QImage.Format_RGB888)
        self.label_qrcode.setPixmap(QPixmap.fromImage(showImage))

        if is_reg == False and self.qr_decoder.total > 1000000:  # 跳过注册检查
            self.thread.cancel()
            QMessageBox.information(self, '信息提示对话框', '未注册，接受文件大小超过限制，请注册后再使用!')

    def create_qrcode_batch(self, i):
        real_i = i
        if self.ids is not None:
            real_i = self.ids[i]

        self.lb_qrindex.setText(str(real_i))
        bytes_part = self.data_list[real_i]
        ret = self.cache.get(real_i)
        if ret:
            self.lb_qrcode.setPixmap(ret)
        else:
            pixmap = self.create_qrcode(base64.b64encode(bytes_part))
            self.lb_qrcode.setPixmap(pixmap)
            self.cache.set(real_i, pixmap)

    def open_file(self):
        if self.cb_file.isChecked():
            fileName, fileType = QtWidgets.QFileDialog.getOpenFileName(self, "选取文件", os.getcwd(),
                                                                       "All Files(*);;Text Files(*.txt)")

            if fileName:
                self.lb_filepath.setText(fileName)
                self.txt_input.setPlainText("")
            else:
                self.cb_file.setChecked(False);
        else:
            self.lb_filepath.setText("")

    def btn_gen_click(self):
        zt = self.btnGen.text()
        split_size = int(self.txt_split_size.text().strip())
        if zt == '生成':
            # 创建线程
            data_bytes = None
            start = 0
            if self.cb_file.isChecked():
                data_bytes = read_into_bytes(self.lb_filepath.text())
                (path, filename) = os.path.split(self.lb_filepath.text())
                self.data_list = Encoder.encode(data_bytes, split_size, filename)
            else:
                txt = self.txt_input.toPlainText()
                if len(txt) <= split_size:
                    self.lb_qrnum.setText(str(1))
                    self.lb_qrcode.setPixmap(self.create_qrcode(txt))
                    return
                data_bytes = bytes(txt, encoding="utf8")
                self.data_list = Encoder.encode(data_bytes, split_size, "NO_NAME")

            end = len(self.data_list)

            self.ids = None
            self.lb_qrnum.setText(str(end))
            if self.cb_miss.isChecked():
                ids = self.txt_input_miss.toPlainText()
                ids = ids.split(",")
                ids = [int(i) for i in ids]
                if len(ids) <= 2:
                    start = ids[0]
                    end = ids[1]
                else:
                    self.ids = ids
                    start = 0
                    end = len(ids)
            else:
                self.txt_input_miss.setPlainText(str(start) + "," + str(end))
            self.thread = Runthread(start, end, int(self.txt_sleep_gen.text().strip()))
            # 连接信号
            self.thread.signal.connect(self.create_qrcode_batch)  # 进程连接回传到GUI的事件
            # 开始线程
            self.cache.clear()
            self.thread.start()
            self.btnGen.setText('停止')
        else:
            self.thread.cancel()  # 停止线程
            self.btnGen.setText('生成')


    def register(self):
        text, ok = QInputDialog.getText(self, '验证注册码', '请输入注册码：')
        ok = Register().regist(text)
        if ok:
            self.label_regtip.setText('已注册')
            QMessageBox.information(self, '信息提示对话框', '注册成功')
        else:
            self.label_regtip.setText('注册失败')
            QMessageBox.information(self, '信息提示对话框', '注册失败')


class Runthread(QtCore.QThread):
    # 通过类成员对象定义信号对象
    _signal = pyqtSignal(int)

    def __init__(self, i_start, i_end, sleep_time):
        super(Runthread, self).__init__()
        self.flag = 0
        self.i_start = i_start
        self.i_end = i_end
        self.sleep_time = sleep_time

        self.isPause = False
        self.isCancel = False
        self.cond = QWaitCondition()
        self.mutex = QMutex()

    # 暂停
    def pause(self):
        print("线程暂停")
        self.isPause = True

    # 恢复
    def resume(self):
        print("线程恢复")
        self.isPause = False
        self.cond.wakeAll()

    # 取消
    def cancel(self):
        print("线程取消")
        self.isCancel = True

    # 运行(入口)
    def run(self):
        while not self.isCancel:
            # 线程锁on
            self.mutex.lock()
            if self.isPause:
                self.cond.wait(self.mutex)
            if self.i_start != self.i_end:
                for i in range(self.i_start, self.i_end):
                    if self.isCancel:
                        break
                    self._signal.emit(i)
                    self.msleep(self.sleep_time)
            else:
                if not self.isPause:
                    self._signal.emit(0)
                    self.msleep(self.sleep_time)
            # 线程锁off
            self.mutex.unlock()
        self._signal.emit(-1)

    @property
    def signal(self):
        return self._signal


class Register:
    def __init__(self):
        self.Des_key = "@9527Tjv"  # Key,需八位
        self.Des_IV = "\x11\2\x2a\3\1\x27\2\0"  # 自定IV向量

    # 获取硬件信息，输出macode
    # 1、CPU序列号（ID）  2、本地连接 无线局域网 以太网的MAC  3.硬盘序列号（唯一） 4.主板序列号（唯一）
    global s
    s = wmi.WMI()

    # cpu序列号
    def get_CPU_info(self):
        cpu = []
        cp = s.Win32_Processor()
        for u in cp:
            cpu.append(
                {
                    "Name": u.Name,
                    "Serial Number": u.ProcessorId,
                    "CoreNum": u.NumberOfCores
                }
            )
        return cpu

    # 硬盘序列号
    def get_disk_info(self):
        disk = []
        for pd in s.Win32_DiskDrive():
            disk.append(
                {
                    "Serial": s.Win32_PhysicalMedia()[0].SerialNumber.lstrip().rstrip(),  # 获取硬盘序列号，调用另外一个win32 API
                    "ID": pd.deviceid,
                    "Caption": pd.Caption,
                    "size": str(int(float(pd.Size) / 1024 / 1024 / 1024))
                }
            )
        return disk

    # mac地址（包括虚拟机的）
    def get_network_info(self):
        network = []
        for nw in s.Win32_NetworkAdapterConfiguration():
            if nw.MacAddress != None:
                network.append(
                    {
                        "MAC": nw.MacAddress,
                        "ip": nw.IPAddress
                    }
                )
        return network

    # 主板序列号
    def get_mainboard_info(self):
        mainboard = []
        for board_id in s.Win32_BaseBoard():
            mainboard.append(board_id.SerialNumber.strip().strip('.'))
        return mainboard

    # 由于机器码矿太长，故选取机器码字符串部分字符
    def getCombinNumber(self):
        a = self.get_network_info()
        b = self.get_CPU_info()
        c = self.get_disk_info()
        d = self.get_mainboard_info()
        machinecode_str = ""
        machinecode_str = machinecode_str + a[0]['MAC'] + b[0]['Serial Number'] + c[0]['Serial'] + d[0]

        selectIndex = [3, 5, 8, 10, 15, 16, 17, 30, 32, 38, 43]
        macode = ""
        num = len(machinecode_str)
        for i in selectIndex:
            if i < num:
                macode = macode + machinecode_str[i]

        if macode.find(":") == 0:
            macode = macode[1:]
        return macode

    # DES+base64加密
    def Encryted(self, tr):
        k = des(self.Des_key, CBC, self.Des_IV, pad=None, padmode=PAD_PKCS5)
        EncryptStr = k.encrypt(tr)
        return base64.b32encode(EncryptStr)  # 转base64编码返回

    # 获取注册码，验证成功后生成注册文件
    def regist(self, key):
        # 由于输入类似“12”这种不符合base64规则的字符串会引起异常，所以需要增加输入判断
        key = key.strip()
        if key:
            ontent = self.getCombinNumber()
            tent = bytes(ontent, encoding='utf-8')
            # 得到加密后机器码
            content = self.Encryted(tent)
            key_decrypted = bytes(key, encoding='utf-8')
            if content != 0 and key_decrypted != 0:
                if content == key_decrypted:
                    print("register succeed.")
                    # 读写文件要加判断
                    with open('register.txt', 'w') as f:
                        f.write(key)
                        f.close()
                    return True
        return False

    # 打开程序先调用注册文件，比较注册文件中注册码与此时的硬件信息编码后是否一致
    def checkAuthored(self):
        ontent = self.getCombinNumber()
        tent = bytes(ontent, encoding='utf-8')
        # 获得加密后的机器码
        content = self.Encryted(tent)
        # 读写文件要加判断
        try:
            f = open('register.txt', 'r')
            if f:
                key = f.read()
                if key:
                    key_decryted = bytes(key.strip(), encoding='utf-8')
                    if key_decryted == content:
                        return True
        except Exception as e:
            print(e)
            return False


is_reg = True # 跳过注册
if __name__ == "__main__":
    app = QApplication(sys.argv)
    ui = MyDesigner()
    ui.move(QDesktopWidget().availableGeometry().center())
    ui.setFixedSize(920, 665)
    try:   # 跳过注册检查
        reg = Register()
    #     is_reg = reg.checkAuthored()
    except Exception as e:
        print(e)
    if is_reg:
        ui.label_regtip.setText('已注册')
    ui.label_macode.setText(reg.getCombinNumber())
    ui.lb_qrcode.setScaledContents(True)
    ui.label_qrcode.setScaledContents(True)
    ui.show()
    sys.exit(app.exec_())



